package com.liaoyin.travel.gate;


import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import com.liaoyin.travel.bean.UserInfo;
import com.liaoyin.travel.util.JsonUtil;
import com.liaoyin.travel.util.RedisUtil;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class JWTAuthenticationFilter extends OncePerRequestFilter {
    

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${spring.jwt.header}")
    private String tokenHeader;
    //过期时间
    @Value("${spring.jwt.expiration}")
    private Long expiration;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        if("OPTIONS".equals(request.getMethod())) {
        	 response.setHeader("Access-Control-Allow-Origin", "*");
             response.setHeader("Access-Control-Allow-Headers", "Origin,accept,Content-Type,Authorization,access-token,X-Requested-With,X_Requested_With");
             //预检请求的缓存时间（秒），即在这个时间段里，对于相同的跨域请求不会再预检了
             response.setHeader("Access-Control-Max-Age", expiration.toString());
             return;
        }

       // UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
     //   SecurityContextHolder.getContext().setAuthentication(authentication);
        //从header里获取token
        String authToken = request.getHeader(this.tokenHeader);
        List<String> urlArr = new ArrayList<>();
        //白名单
        urlArr.add("/swagger");
        urlArr.add("/upload");
        urlArr.add("/webjars");
        urlArr.add("/file");
        urlArr.add("/api");
        urlArr.add("/v2");
        urlArr.add("/dictBasic");
        urlArr.add("/sUsers");
        urlArr.add("/back");
        urlArr.add("/moble/");
        urlArr.add("/menu/");
        urlArr.add("/epidemicPrevention/");
        urlArr.add("/role/");
        urlArr.add("/websocket");
        urlArr.add("/externalApi");//对外接口
        urlArr.add("/all");
       // urlArr.add("/moble/register");
        urlArr.add("/usersManagement");
        Boolean flag = true;
        for(String uri:urlArr){
            //System.out.println(request.getRequestURI());
            if(request.getRequestURI().startsWith(uri)){
            	flag = false;
                chain.doFilter(request, response);
            }
        }
        //存在的情况
        if(flag) {
             if (StringUtils.isNotBlank(authToken)) {             
                //验证token是否有效
                UserInfo user = null;
				try {
					user = JsonUtil.getSingleBean(RedisUtil.get(JwtTokenUtil.getRedisKeyFromToken(authToken),String.class),UserInfo.class);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
                if (SecurityContextHolder.getContext().getAuthentication() == null) {
                    if (jwtTokenUtil.validateToken(authToken, user.getPhone()+"#"+user.getId())) {
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                                user, null, null);
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        logger.info("authenticated user " + user.getPhone() + ", setting security context");
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                        //刷新redis里旧token的时间为1800秒
                        RedisUtil.expire(RedisUtil.get(JwtTokenUtil.getRedisKeyFromToken(authToken),String.class), (long) this.expiration/1000);
                        chain.doFilter(request, response);
                    }
                }
                
             }
        }
    }
}
